﻿using System;
using System.Drawing;
using System.Runtime.Serialization;
using System.Windows.Forms;
namespace ShapeManager
{
    /// <summary> 绘制对象：形状的初始化、绘制、拷贝、保存、加载... </summary>
    public abstract class DrawObject : Shape
    {
        #region 构造函数
        public DrawObject()
        {
            ID = this.GetHashCode();
        }
        #endregion

        #region 标准、初始化
        /// <summary> 标准化  </summary>
        public virtual void Normalize(){}
        protected void Initialize()
        {
            //BorderColor = lastUsedColor;
            //BorderWidth = LastUsedPenWidth;
        }
        #endregion

        #region 基础方法
        /// <summary> 克隆方法  </summary> 
        public abstract DrawObject Clone();
        /// <summary> 浅拷贝：将此实例中的字段复制到克隆实例“drawObject”中。 由派生类的克隆函数调用。 </summary>
        public void Clone( DrawObject drawObject)
        {
            try
            {
                drawObject = (DrawObject)MemberwiseClone();
                drawObject.ID = this.ID;
            }
            catch (System.Exception ex)
            {
                return ;
            }
        }
        /// <summary> 绘制方法 </summary>
        public abstract void Draw(Graphics graphics);
        /// <summary> 移动方法 </summary>
        public virtual void Move(float deltaX, float deltaY)
        {
        }
        /// <summary> 移动手柄到新的点（调整角度） </summary>
        public virtual void Rotate(PointF point1,PointF point2)
        {
        }
        /// <summary> 移动手柄到新的点（调整大小） </summary>
        public virtual void MoveHandleTo(PointF point, int handleNumber)
        {
        }
        /// <summary> 获取基于1编号的手柄点 </summary> 
        public virtual PointF GetHandle(int handleNumber)
        {
            return new PointF(0, 0);
        }
        /// <summary> 通过基于1的编号获取矩形的控制柄。 </summary> 
        public virtual RectangleF GetHandleRectangle(int handleNumber)
        {
            PointF point = GetHandle(handleNumber);
            return new RectangleF(point.X - 3, point.Y - 3, 7, 7);
        }
        /// <summary> 为选定对象绘制所有手柄 </summary> 
        public virtual void DrawHandles(Graphics g)
        {
            if (!IsSelected) return;
            using (SolidBrush brush = new SolidBrush(Color.FromArgb(200,HandleColor)))
            {
                for (int i = 1; i <= HandleCount; i++)
                {
                    g.FillEllipse(brush, GetHandleRectangle(i));
                }
            }
        }
        /// <summary> 命中测试 ： 返回值: -1 - 未命中 0 - 任意点命中 > 1 - 手柄编号  </summary> 
        public virtual int HitTest(PointF point)
        {
            return -1;
        }
        /// <summary> 点在对象区域内 </summary>
        protected virtual bool PointInObject(PointF point)
        {
            return false;
        }
        /// <summary> 获取手柄 </summary>
        public virtual Cursor GetHandleCursor(int handleNumber)
        {
            return Cursors.Default;
        }
        /// <summary> 矩形相交 </summary>
        public virtual bool IntersectsWith(RectangleF rectangle)
        {
            return false;
        }
        #endregion

        #region 辅助方法
        public virtual void DrawCenter(Graphics graphics)
        {
            RectangleF rectangle = Region;
            // 1、计算矩形中心坐标
            float centerX = rectangle.X + rectangle.Width / 2;
            float centerY = rectangle.Y + rectangle.Height / 2;
            // 2、线长度大小（根据矩形大小自适应）
            float lineHalfLength = 3;
            // 3、绘制箭头
            using (Pen arrowPen = new Pen(BackColor, BorderWidth))
            {
                // 3.1 水平线
                PointF left = new PointF(centerX - lineHalfLength, centerY);
                PointF right = new PointF(centerX + lineHalfLength, centerY);
                graphics.DrawLine(arrowPen, left, right);
                // 3.2 垂直线
                PointF top = new PointF(centerX, centerY - lineHalfLength);
                PointF bottom = new PointF(centerX, centerY + lineHalfLength);
                graphics.DrawLine(arrowPen, top, bottom);
            }
        }
        #endregion

        #region 数据保存、加载
        /// <summary> 将对象保存到序列化流中  </summary> 
        public virtual void SaveToStream(SerializationInfo info, int orderNumber)
        {
            info.AddValue($"{entryColor}{orderNumber}", BorderColor.ToArgb());
            info.AddValue($"{entryPenWidth}{orderNumber}", BorderWidth);
        }
        /// <summary> 从序列化流中加载对象 </summary> 
        public virtual void LoadFromStream(SerializationInfo info, int orderNumber)
        {
            ID = this.GetHashCode();
            int n = info.GetInt32($"{entryColor}{orderNumber}");
            BorderColor = Color.FromArgb(n);
            BorderWidth = info.GetInt32($"{entryColor}{orderNumber}");
        }
        #endregion

    }
}
